#include <stdio.h>
#include <string>
#include "BitImage.h"
#include "JpegImage.h"
#include "PngImage.h"
#include "Image.h"
#include "Conver.h"
#include "Param.h"

using namespace std;
using std::char_traits;

static const char *imageErrorString[] = 
{
    "image not init",
    "can not found image",
    "not a legal image, only support for .bmp .jpg/jpeg .png",
};

int main(int argc, const char *argv[])
{
    if(argc == 1)
    {
        printf("Plese add \"-h\" param to show help information\n");
        return 0;
    }

    int error;
    ConverParam *param = ConverParamDecode(argc, argv, &error);     //进行参数解析
    if(error != 0)
    {
        printf("param error: %s\n", ParamErrorToString(error));
        return 0;
    }
    if(param == nullptr)        //error为0但param为nullptr表示显示帮助信息(已显示)
        return 0;

    //进行图片解码
    Image *img = nullptr;

    const char *pfile = strrchr(param->inputFileName.c_str(), '.');     //获取文件后缀
    if(!strcasecmp(pfile, ".bmp"))
        img = new BitImage(param->inputFileName);
    else if(!strcasecmp(pfile, ".jpg") || !strcasecmp(pfile, ".jpeg"))
        img = new JpegImage(param->inputFileName);
    else if(!strcasecmp(pfile, ".png"))
        img = new PngImage(param->inputFileName);  

    if(img == nullptr)
        return 0;

    Image::ImageStatus status = img->GetStatus();
    if(status != Image::IMAGE_OK)       //图片解码失败
    {
        printf("conver %s failed! error:%s\n", param->inputFileName.c_str(), imageErrorString[abs(status) - 1]);
        return 0;
    }

    //获取图片信息
    Image::ImageInfo info = img->GetInfo();

    int h = info.height;
    int w = info.width;
    int bpp = info.bpp;

    uint8_t *imgBuf = new uint8_t[w * h * bpp];
    img->GetImage(imgBuf, h);

    //创建转换目标文件
    string outFile = param->outPath + param->outFileName;       //目标文件名
    FILE *file = fopen(outFile.c_str(), "w");
    if(file == NULL)
        return -1;
    
    //若输出文件名有后缀，则删除，C变量名不能出现'.'
    int dotPos = param->outFileName.find_last_of('.', string::npos);
        if (dotPos != string::npos)     // 找到后缀
            param->outFileName = param->outFileName.substr(0, dotPos);

    info.name = param->outFileName;     //设置C输出名
    uint32_t cfg = param->format | (param->imgcfg << 30);   //设置转换参数
    if(param->is_big_endian)
    {
        cfg |= 0x00001000;
    }
    //转换图片，并写入文件
    ConverToFile(file, imgBuf, info, cfg, (ConverFile)param->outFile);

    fclose(file);

    printf("conver \"%s\" complete!\n", param->inputFileName.c_str());

    delete[] imgBuf;
    delete img;

    return 0;
}
